package com.qiaoba.module.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.qiaoba.api.auth.utils.SecurityUtil;
import com.qiaoba.api.system.constant.SysUserConstant;
import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.common.base.exception.ServiceException;
import com.qiaoba.common.base.util.ObjectUtil;
import com.qiaoba.module.system.entity.*;
import com.qiaoba.module.system.entity.param.SysDeptParam;
import com.qiaoba.module.system.entity.param.SysPostParam;
import com.qiaoba.module.system.entity.param.SysRoleParam;
import com.qiaoba.module.system.entity.template.SysUserImport;
import com.qiaoba.module.system.mapper.SysUserMapper;
import com.qiaoba.module.system.service.SysDeptService;
import com.qiaoba.module.system.service.SysPostService;
import com.qiaoba.module.system.service.SysRoleService;
import com.qiaoba.module.system.service.SysUserImportService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户导入 服务层实现
 *
 * @author ailanyin
 * @date 2023-09-16 10:41:14
 */
@Service
@RequiredArgsConstructor
public class SysUserImportServiceImpl implements SysUserImportService {

    private static ThreadLocal<List<String>> DEPT_IDS = new ThreadLocal<>();
    private static ThreadLocal<List<String>> USERNAME_LIST = new ThreadLocal<>();
    private static ThreadLocal<List<String>> PHONE_LIST = new ThreadLocal<>();
    private static ThreadLocal<List<String>> EMAIL_LIST = new ThreadLocal<>();
    private static ThreadLocal<List<String>> ROLE_IDS = new ThreadLocal<>();
    private static ThreadLocal<List<String>> POST_IDS = new ThreadLocal<>();
    private static ThreadLocal<List<SysUserRole>> USER_ROLE_LIST = new ThreadLocal<>();
    private static ThreadLocal<List<SysUserPost>> USER_POST_LIST = new ThreadLocal<>();

    private final SysDeptService sysDeptService;
    private final SysRoleService sysRoleService;
    private final SysPostService sysPostService;
    private final SysUserMapper sysUserMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importUserData(List<SysUserImport> userImportList) {
        beforeImport();
        try {
            if (CollUtil.isEmpty(userImportList)) {
                throw new ServiceException("导入用户数据不能为空！");
            }
            // 检查参数
            checkData(userImportList);
            // 检查唯一性
            checkExist();
            // 构造userList|userRoleList|userPostList
            List<SysUser> userList = createUserList(userImportList);
            // 插入数据
            batchInsert(userList);
            return "恭喜！成功导出【" + USERNAME_LIST.get().size() + "】条数据！";
        } finally {
            afterImport();
        }

    }


    private void batchInsert(List<SysUser> userList) {
        // 插入用户
        Db.saveBatch(userList);
        // 插入用户角色
        Db.saveBatch(USER_ROLE_LIST.get());
        // 插入用户岗位
        if (CollUtil.isNotEmpty(USER_POST_LIST.get())) {
            Db.saveBatch(USER_POST_LIST.get());
        }
    }

    private List<SysUser> createUserList(List<SysUserImport> userImportList) {
        List<SysUser> list = new ArrayList<>();

        for (SysUserImport sysUserImport : userImportList) {
            String userId = IdUtil.getSnowflakeNextIdStr();
            SysUser sysUser = new SysUser();
            sysUser.setUserId(userId);
            sysUser.setDeptId(sysUserImport.getDeptId());
            sysUser.setUsername(sysUserImport.getUsername());
            sysUser.setNickname(sysUserImport.getNickname());
            sysUser.setEmail(sysUserImport.getEmail());
            sysUser.setPhone(sysUserImport.getPhone());
            sysUser.setGender(sysUserImport.getGender());
            sysUser.setPassword(SecurityUtil.encryptPassword(sysUserImport.getPassword()));
            sysUser.setStatus(BaseConstant.NORMAL);
            list.add(sysUser);

            handleRole(userId, sysUserImport.getRoleIds());
            handlePost(userId, sysUserImport.getPostIds());
        }

        return list;
    }

    private void handleRole(String userId, String roleIds) {
        for (String roleId : roleIds.split(BaseConstant.LINE_JOIN_STR)) {
            USER_ROLE_LIST.get().add(new SysUserRole(userId, roleId));
        }
    }

    private void handlePost(String userId, String postIds) {
        if (StrUtil.isBlank(postIds)) {
            return;
        }
        for (String postId : postIds.split(BaseConstant.LINE_JOIN_STR)) {
            USER_POST_LIST.get().add(new SysUserPost(userId, postId));
        }
    }

    private void checkData(List<SysUserImport> userImportList) {
        for (SysUserImport sysUserImport : userImportList) {
            // 去除空行(所有字段为空 = 空行)
            if (ObjectUtil.allFieldsIsEmpty(sysUserImport)) {
                continue;
            }
            // 检查账号
            checkUsername(sysUserImport.getUsername());
            // 检查密码
            checkPassword(sysUserImport.getPassword(), sysUserImport.getUsername());
            // 检查姓名
            checkNickname(sysUserImport.getNickname(), sysUserImport.getUsername());
            // 检查手机
            checkPhone(sysUserImport.getPhone(), sysUserImport.getUsername());
            // 检查邮箱
            checkEmail(sysUserImport.getEmail(), sysUserImport.getUsername());
            // 检查部门
            checkDept(sysUserImport.getDeptId(), sysUserImport.getUsername());
            // 检查角色
            checkRole(sysUserImport.getRoleIds(), sysUserImport.getUsername());
            // 检查岗位
            checkPost(sysUserImport.getPostIds(), sysUserImport.getUsername());
        }
    }

    private void checkExist() {
        // 登陆账号
        String username = sysUserMapper.batchCheckUsernameUnique(USERNAME_LIST.get());
        if (StrUtil.isNotBlank(username)) {
            throw new ServiceException("登陆账号【" + username + "】已存在！");
        }
        // 手机号
        if (CollUtil.isNotEmpty(PHONE_LIST.get())) {
            String phone = sysUserMapper.batchCheckPhoneUnique(PHONE_LIST.get());
            if (StrUtil.isNotBlank(phone)) {
                throw new ServiceException("手机号【" + phone + "】已存在！");
            }
        }
        // 邮箱
        if (CollUtil.isNotEmpty(EMAIL_LIST.get())) {
            String email = sysUserMapper.batchCheckEmailUnique(EMAIL_LIST.get());
            if (StrUtil.isNotBlank(email)) {
                throw new ServiceException("邮箱号【" + email + "】已存在！");
            }
        }
    }

    private void beforeImport() {
        // 查询所有部门IDS
        DEPT_IDS.set(sysDeptService.selectList(new SysDeptParam())
                .stream()
                .map(SysDept::getDeptId)
                .collect(Collectors.toList()));
        // 查询所有角色IDS
        ROLE_IDS.set(sysRoleService.selectList(new SysRoleParam())
                .stream()
                .map(SysRole::getRoleId)
                .collect(Collectors.toList()));
        // 查询所有岗位IDS
        POST_IDS.set(sysPostService.selectList(new SysPostParam())
                .stream()
                .map(SysPost::getPostId)
                .collect(Collectors.toList()));
        // USER_ROLE_LIST
        USER_ROLE_LIST.set(new ArrayList<>());
        // USER_POST_LIST
        USER_POST_LIST.set(new ArrayList<>());
        // USERNAME_LIST
        USERNAME_LIST.set(new ArrayList<>());
        // PHONE_LIST
        PHONE_LIST.set(new ArrayList<>());
        // EMAIL_LIST
        EMAIL_LIST.set(new ArrayList<>());
    }

    private void afterImport() {
        DEPT_IDS.remove();
        ROLE_IDS.remove();
        POST_IDS.remove();
        USER_ROLE_LIST.remove();
        USER_POST_LIST.remove();
        USERNAME_LIST.remove();
        PHONE_LIST.remove();
        EMAIL_LIST.remove();
    }

    private void checkUsername(String username) {
        if (StrUtil.isBlank(username)) {
            throw new ServiceException("登陆账号不能为空！");
        }
        if (!username.matches(SysUserConstant.USERNAME_REGEX)) {
            throw new ServiceException("登陆账号【" + username + "】格式不正确！");
        }
        // 将username插入到临时变量中, 后期检查唯一性
        USERNAME_LIST.get().add(username);
    }

    private void checkPassword(String password, String username) {
        if (StrUtil.isBlank(password)) {
            throw new ServiceException("账号【" + username + "】的登陆密码不能为空！");
        }
        if (!password.matches(SysUserConstant.PASSWORD_REGEX)) {
            throw new ServiceException("账号【" + username + "】的登陆密码【" + password + "】格式不正确！");
        }
    }

    private void checkNickname(String nickname, String username) {
        if (StrUtil.isBlank(nickname)) {
            throw new ServiceException("账号【" + username + "】的用户姓名不能为空！");
        }
        if (!nickname.matches(SysUserConstant.NICKNAME_REGEX)) {
            throw new ServiceException("账号【" + username + "】的用户姓名【" + nickname + "】格式不正确！");
        }
    }

    private void checkPhone(String phone, String username) {
        if (StrUtil.isNotBlank(phone)) {
            if (!phone.matches(RegexPool.MOBILE)) {
                throw new ServiceException("账号【" + username + "】的手机号【" + phone + "】格式不正确！");
            }
            // 将phone插入到临时变量中, 后期检查唯一性
            PHONE_LIST.get().add(phone);
        }

    }

    private void checkEmail(String email, String username) {
        if (StrUtil.isNotBlank(email)) {
            if (!email.matches(RegexPool.EMAIL)) {
                throw new ServiceException("账号【" + username + "】的邮箱【" + email + "】格式不正确！");
            }
            // 将email插入到临时变量中, 后期检查唯一性
            EMAIL_LIST.get().add(email);
        }
    }

    private void checkDept(String deptId, String username) {
        if (StrUtil.isNotBlank(deptId) && !DEPT_IDS.get().contains(deptId)) {
            throw new ServiceException("账号【" + username + "】的部门ID【" + deptId + "】不存在！");
        }
    }

    private void checkRole(String roleIds, String username) {
        if (StrUtil.isBlank(roleIds)) {
            throw new ServiceException("账号【" + username + "】的角色ID不能为空！");
        }
        for (String roleId : roleIds.split(BaseConstant.LINE_JOIN_STR)) {
            if (!ROLE_IDS.get().contains(roleId)) {
                throw new ServiceException("账号【" + username + "】的角色ID【" + roleId + "】不存在！");
            }
        }
    }

    private void checkPost(String postIds, String username) {
        if (StrUtil.isBlank(postIds)) {
            return;
        }
        for (String postId : postIds.split(BaseConstant.LINE_JOIN_STR)) {
            if (!POST_IDS.get().contains(postId)) {
                throw new ServiceException("账号【" + username + "】的岗位ID【" + postId + "】不存在！");
            }
        }
    }

}
